{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 1、练习线性回归之梯度下降，Lasso回归，岭回归，理解原理是核心",
   "id": "92d9660e13292016"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": " 导入包",
   "id": "62a0051cc2253ccc"
  },
  {
   "cell_type": "code",
   "id": "initial_id",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-03-04T00:09:11.951840Z",
     "start_time": "2025-03-04T00:09:07.305524Z"
    }
   },
   "source": [
    "import numpy as np\n",
    "from sklearn.datasets import fetch_california_housing  # 导入数据集\n",
    "from sklearn.linear_model import LinearRegression, SGDRegressor  # 线性回归，梯度下降\n",
    "from sklearn.model_selection import train_test_split  # 划分数据集\n",
    "from sklearn.preprocessing import StandardScaler  # 标准化\n",
    "from sklearn.metrics import mean_squared_error  # 均方误差\n",
    "import joblib  # 保存模型\n",
    "import os  # 删除模型"
   ],
   "outputs": [],
   "execution_count": 1
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 线性回归：正规方程法",
   "id": "f784fcb7f2d667b9"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-04T00:09:11.954463Z",
     "start_time": "2025-03-04T00:09:11.952845Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 线性回归通过一个或者多个自变量与因变量之间进行建模的回归分析。预测结果与真实值是有一定的误差\n",
    "# 通用公式：y = a + b*x1 + c*x2 +... + n*xn\n",
    "# 损失函数：就是误差的度量，比如平方误差"
   ],
   "id": "d9631e23b9f35fe2",
   "outputs": [],
   "execution_count": 2
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "数据预处理",
   "id": "e6ddcd9571546056"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-04T00:09:11.976237Z",
     "start_time": "2025-03-04T00:09:11.954463Z"
    }
   },
   "cell_type": "code",
   "source": [
    "\"\"\"\n",
    "加利福利亚住房数据集\n",
    "\"\"\"\n",
    "cal_housing = fetch_california_housing(data_home='.')\n",
    "print(f\"特征值的shape：{cal_housing.data.shape}\")  # cal_housing.data：只能加.data才能取出数据,共有20640个样本，每个样本有8个特征\n",
    "print(f\"取出样本的特征名:{cal_housing.feature_names}\")\n",
    "print(f'取出一个样本观察：{cal_housing.data[0]}')\n"
   ],
   "id": "236276908a16c24c",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "特征值的shape：(20640, 8)\n",
      "取出样本的特征名:['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population', 'AveOccup', 'Latitude', 'Longitude']\n",
      "取出一个样本观察：[   8.3252       41.            6.98412698    1.02380952  322.\n",
      "    2.55555556   37.88       -122.23      ]\n"
     ]
    }
   ],
   "execution_count": 3
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "MedInc - 中位收入（Median Income）\n",
    "HouseAge - 房屋年龄（House Age）\n",
    "AveRooms - 平均房间数（Average Number of Rooms）\n",
    "AveBedrms - 平均卧室数（Average Number of Bedrooms）\n",
    "Population - 人口数量（Population）\n",
    "AveOccup - 平均居住人数（Average Occupancy）\n",
    "Latitude - 纬度（Latitude）\n",
    "Longitude - 经度（Longitude）"
   ],
   "id": "96e800570817aa1"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-04T00:09:11.982701Z",
     "start_time": "2025-03-04T00:09:11.976237Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 分割数据集\n",
    "x_train, x_test, y_train, y_test = train_test_split(cal_housing.data, cal_housing.target, test_size=0.25,\n",
    "                                                    random_state=1)\n",
    "print(x_train.shape)  # (15480, 8)\n",
    "# 标准化\n",
    "std = StandardScaler()\n",
    "x_train = std.fit_transform(x_train)\n",
    "x_test = std.transform(x_test)\n",
    "\n",
    "# 对目标变量进行标准化\n",
    "std_y = StandardScaler()\n",
    "print(y_train.shape)  # (15480,)\n",
    "# y_train = std_y.fit_transform(y_train.reshape(-1, 1))  # 转换成列向量,因为y_train是一维数组，而LinearRegression要求输入是2维的"
   ],
   "id": "2441102023b534b3",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(15480, 8)\n",
      "(15480,)\n"
     ]
    }
   ],
   "execution_count": 4
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "机器学习模型：线性回归",
   "id": "6c713108d06b4a7f"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "未对目标值进行标准化处理的训练代码",
   "id": "b671af2bd1270dc5"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-04T00:09:11.993653Z",
     "start_time": "2025-03-04T00:09:11.982701Z"
    }
   },
   "cell_type": "code",
   "source": [
    "lr = LinearRegression()  # 实例化线性回归模型\n",
    "lr.fit(x_train, y_train)  # 训练模型\n",
    "print(f\"回归系数：{lr.coef_}\")  #coef_：系数\n",
    "y_pred = lr.predict(x_test)  # 预测结果:是模型根据训练数据集学习到的参数，对测试数据集的输入进行预测\n",
    "# 保存模型，如果存在则覆盖\n",
    "try:\n",
    "    # 删除之前存在的模型\n",
    "    os.unlink('./lr.pkl')\n",
    "except:\n",
    "    pass\n",
    "joblib.dump(lr, './lr.pkl')  # 保存模型,保存到当前目录下\n",
    "print(f\"模型保存成功！\")\n",
    "print(y_pred.shape)\n",
    "print(f\"正规方程法预测结果：{y_pred[0:10]}\")  # 显示前10个预测结果\n",
    "# print(f\"正规方程的均方误差是：{np.mean((y_pred - y_test) ** 2)}\")\n",
    "print(f\"正规方程的均方误差是：{mean_squared_error(y_pred, y_test)}\")  # 在线性回归中，均方误差是衡量预测值与真实值的差距的一种常用指标\n",
    "# inverse_transform()方法可以将标准化后的数据还原\n",
    "\n"
   ],
   "id": "61c769bddb438e6a",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "回归系数：[ 0.83167028  0.12159502 -0.26758589  0.30983997 -0.00518054 -0.04040421\n",
      " -0.90736902 -0.88212727]\n",
      "模型保存成功！\n",
      "(5160,)\n",
      "正规方程法预测结果：[2.12391852 0.93825754 2.7088455  1.70873764 2.82954754 3.50376456\n",
      " 3.0147162  1.62781292 1.74317518 2.01897806]\n",
      "正规方程的均方误差是：0.5356532845422556\n"
     ]
    }
   ],
   "execution_count": 5
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "对目标值进行标准化处理的训练代码",
   "id": "caa2bdb5666f0bea"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "重新划分数据集，对目标值进行标准化处理",
   "id": "5a2114faf585fd5f"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-04T00:09:11.999253Z",
     "start_time": "2025-03-04T00:09:11.993653Z"
    }
   },
   "cell_type": "code",
   "source": [
    "x_train, x_test, y_train, y_test =train_test_split(cal_housing.data, cal_housing.target, test_size=0.25, random_state=1)\n",
    "std_x = StandardScaler()\n",
    "x_train = std_x.fit_transform(x_train)\n",
    "x_test = std_x.transform(x_test)\n",
    "std_y = StandardScaler()\n",
    "y_train = std_y.fit_transform(y_train.reshape(-1, 1))  # 转换成列向量"
   ],
   "id": "711231fd46ba477a",
   "outputs": [],
   "execution_count": 6
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "机器学习模型：正规方程法",
   "id": "16e7255e519359bf"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-04T00:09:12.006302Z",
     "start_time": "2025-03-04T00:09:11.999253Z"
    }
   },
   "cell_type": "code",
   "source": [
    "lr = LinearRegression()\n",
    "# fit是耗时的\n",
    "lr.fit(x_train, y_train)\n",
    "#回归系数可以看特征与目标之间的相关性\n",
    "print('回归系数', lr.coef_)\n",
    "#\n",
    "y_predict = lr.predict(x_test)\n",
    "# 保存训练好的模型，模型中保存的是w的值，也保存了模型结构\n",
    "# 预测测试集的房子价格，通过inverse得到真正的房子价格\n",
    "y_lr_predict = std_y.inverse_transform(y_predict)\n",
    "#保存模型放在fit之后即可\n",
    "\n",
    "print(\"正规方程测试集里面每个房子的预测价格：\", y_lr_predict[0:10])\n",
    "print(\"正规方程的均方误差：\", mean_squared_error(y_test, y_lr_predict))"
   ],
   "id": "593a07cc9b958a56",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "回归系数 [[ 0.71942632  0.10518431 -0.23147194  0.26802332 -0.00448136 -0.03495117\n",
      "  -0.7849086  -0.76307353]]\n",
      "正规方程测试集里面每个房子的预测价格： [[2.12391852]\n",
      " [0.93825754]\n",
      " [2.7088455 ]\n",
      " [1.70873764]\n",
      " [2.82954754]\n",
      " [3.50376456]\n",
      " [3.0147162 ]\n",
      " [1.62781292]\n",
      " [1.74317518]\n",
      " [2.01897806]]\n",
      "正规方程的均方误差： 0.5356532845422556\n"
     ]
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 线性回归：梯度下降法",
   "id": "f5bc93d9561e213a"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "数据预处理",
   "id": "fe3432bb6b5474e1"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-04T00:09:12.015090Z",
     "start_time": "2025-03-04T00:09:12.006302Z"
    }
   },
   "cell_type": "code",
   "source": [
    "\"\"\"\n",
    "加利福利亚住房数据集\n",
    "\"\"\"\n",
    "cal_housing = fetch_california_housing(data_home='.')\n",
    "print(f\"特征值的shape：{cal_housing.data.shape}\")  # cal_housing.data：只能加.data才能取出数据,共有20640个样本，每个样本有8个特征\n",
    "print(f\"取出样本的特征名:{cal_housing.feature_names}\")\n",
    "print(f'取出一个样本观察：{cal_housing.data[0]}')"
   ],
   "id": "c369b45d1b0e4270",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "特征值的shape：(20640, 8)\n",
      "取出样本的特征名:['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population', 'AveOccup', 'Latitude', 'Longitude']\n",
      "取出一个样本观察：[   8.3252       41.            6.98412698    1.02380952  322.\n",
      "    2.55555556   37.88       -122.23      ]\n"
     ]
    }
   ],
   "execution_count": 8
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-04T00:09:12.020597Z",
     "start_time": "2025-03-04T00:09:12.015090Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 分割数据集\n",
    "x_train, x_test, y_train, y_test = train_test_split(cal_housing.data, cal_housing.target, test_size=0.25,\n",
    "                                                    random_state=1)\n",
    "print(x_train.shape)  # (15480, 8)\n",
    "# 标准化\n",
    "std = StandardScaler()  # 创建一个StandardScaler对象\n",
    "x_train = std.fit_transform(x_train)  # 训练集标准化\n",
    "x_test = std.transform(x_test)  # 测试集标准化\n",
    "\n",
    "# 对目标变量进行标准化\n",
    "std_y = StandardScaler()  # 创建一个StandardScaler对象\n",
    "# y_train = std_y.fit_transform(y_train.reshape(-1, 1))  # 转换成列向量,因为y_train是一维数组，而LinearRegression要求输入是2维的"
   ],
   "id": "55cdfa348734e9f4",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(15480, 8)\n"
     ]
    }
   ],
   "execution_count": 9
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "机器学习模型：梯度下降法",
   "id": "d7834e9e84590a8"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-04T00:09:12.035400Z",
     "start_time": "2025-03-04T00:09:12.020597Z"
    }
   },
   "cell_type": "code",
   "source": [
    "sgd = SGDRegressor(penalty='l2', max_iter=1000, eta0=0.01)  # eta0：学习率，learning rate:步长\n",
    "sgd.fit(x_train, y_train)\n",
    "y_pred = sgd.predict(x_test)\n",
    "\n",
    "print(f\"训练集中梯度下降的损失值：{sgd.coef_}\")  # 训练集中梯度下降的损失值\n",
    "print(f\"测试集上的均方误差：{mean_squared_error(y_test, y_pred)}\")  # 测试集上的均方误差\n",
    "# 事实上每次运行结果都不一样，因为每次运行都会随机初始化参数，导致结果不确定"
   ],
   "id": "2d56a1a5020e0665",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练集中梯度下降的损失值：[ 0.81243506  0.12364248 -0.20695479  0.31491906 -0.00448994 -0.0879624\n",
      " -0.92187772 -0.88760013]\n",
      "测试集上的均方误差：0.5353895753397735\n"
     ]
    }
   ],
   "execution_count": 10
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
